#ifndef xpack_macro_private_xstruct_prop
#define xpack_macro_private_xstruct_prop
#pragma push_macro("xuser")
#undef  xuser
#define xuser mixc::macro_private_xstruct_prop
#include"define/base_type.hpp"
#include"macro/private/xstruct.concept.hpp"
#include"macro/private/xstruct.inc.hpp"
#include"meta_seq/tlist.hpp"
#pragma pop_macro("xuser")


// dummy
struct __child_t{
    template<class> struct __fields{};
    uxx __dummy;
};

template<uxx, class __child_t, class ... __rest_t>
struct __fields_hub{};

template<uxx __dummy_v, class __child_t, class __first_t, class ... __rest_t>
struct __fields_hub<__dummy_v, __child_t, __first_t, __rest_t...> : 
    __first_t::template __fields<__child_t>, __fields_hub<__dummy_v + 1, __child_t, __rest_t...> {
};

template<class __first_t, class __second_t = void>
struct __field_select{
    using type = __second_t;
};

template<class __first_t>
struct __field_select<__first_t, void>{
    using type = __first_t;
};


template<class __base_t>
struct __xstruct_mix_prop{
    using the_t = __xstruct_mix_prop<__base_t>;
    template<class = the_t>
    struct __fields : 
        __base_t, 
        __base_t::template __fields<the_t>{
        using __base_t::__base_t;
    };
};


//// 该写法会导致智能提示失效
// struct __xsturct_dummy{
//     template<class = void> struct __fields{};
// };
//
// template<class __has_fields_t>
// concept __has_fields = ::mixc::macro_private_xstruct_prop::inc::is_empty_class<
//     typename __has_fields_t::template __fields<__xsturct_dummy>
// > == false;

// template<uxx, class __child_t, class ... __rest_t>
// struct __fields_hub;

// template<uxx __dummy_v, class __child_t, class __first_t, class ... __rest_t>
// struct __fields_hub<__dummy_v, __child_t, __first_t, __rest_t...> : 
//     __fields_hub<__dummy_v + 1, __child_t, __rest_t...> {
// };

// template<uxx __dummy_v, class __child_t, __has_fields __first_t, class ... __rest_t>
// struct __fields_hub<__dummy_v, __child_t, __first_t, __rest_t...> : 
//     __first_t::template __fields<__child_t>, __fields_hub<__dummy_v + 1, __child_t, __rest_t...> {
// };

// template<uxx __dummy_v, class __child_t>
// struct __fields_hub<__dummy_v, __child_t>{};


//// 所以使用函数递归生成最终类型
template<class child_t, class ... result_t>
constexpr auto __fields_filter(__xstruct_tl<result_t...>){
    struct foo{
        using type = __fields_hub<0, child_t, result_t...>;

        void dummy(type *){} // 避免编译警告
    };
    return foo{};
}

template<class child_t, class first_t, class ... rest_t, class ... result_t>
constexpr auto __fields_filter(__xstruct_tl<result_t...>){
    return __fields_filter<child_t, rest_t...>(
        __xstruct_tl<result_t...>{}
    );
}

template<class child_t, class first_t, class ... rest_t, class ... result_t>
requires(sizeof(typename first_t::template __fields<>) >= 1)
constexpr auto __fields_filter(__xstruct_tl<result_t...>){
    return __fields_filter<child_t, rest_t...>(
        __xstruct_tl<result_t..., first_t>{}
    );
}



template<class __first_t, class __second_t = void>
using __field_first = typename __field_select<__first_t, __second_t>::type;

#define __xprop_operator()                                              \
    auto operator->() const {                                           \
        if constexpr (__can_operator_this<base_t>){                     \
            return base_t::operator->();                                \
        }                                                               \
        else if constexpr (                                             \
            __xstruct_is_ref<__get_t> and                               \
            __can_operator_this<__get_t>                                \
        ){                                                              \
            auto ptr = & base_t::operator __get_t();                    \
            return (typename                                            \
                ::__xstruct_mix_prop<__xstruct_rr<__get_t>>             \
                ::template __fields<> *                                 \
            )(ptr);                                                     \
        }                                                               \
        else{                                                           \
            return nullptr;                                             \
        }                                                               \
    }                                                                   \
                                                                        \
    template<class index_t = uxx>                                       \
    requires(__can_random_access<__get_t, index_t>)                     \
    decltype(auto) operator[](index_t && index) const {                 \
        return (base_t::operator __get_t()[xforward(index)]);           \
    }                                                                   \
                                                                        \
    template<class index_t = uxx>                                       \
    requires(__can_random_access<__get_t, index_t>)                     \
    decltype(auto) operator[](index_t && index) {                       \
        return (base_t::operator __get_t()[xforward(index)]);           \
    }                                                                   \


#define __xprop_meta(NAME,MODIFY_GET,MODIFY_SET,...)                    \
template<class the_t, class child_t, class base_t>                      \
struct NAME : base_t{                                                   \
    using __get_t = typename base_t::__get_t;                           \
    struct __prop{ enum{ value = true }; };                             \
    friend the_t; __VA_ARGS__                                           \
                                                                        \
    static constexpr bool im_xstruct_prop_get  = true;                  \
    static constexpr bool im_xstruct_prop_set  = true;                  \
MODIFY_GET:                                                             \
    using base_t::operator __get_t;                                     \
                                                                        \
    __get_t operator()() const {                                        \
        return base_t::operator __get_t();                              \
    }                                                                   \
                                                                        \
    __xprop_operator()                                                  \
MODIFY_SET:                                                             \
    using base_t::operator=;                                            \
                                                                        \
    /* base_t 可能没有 __set_t 成员，所以不使用 using __set_t = xxx; */ \
    template<class item_t = __xstruct_rr<typename base_t::__set_t>>     \
    requires(__can_prop_assign<base_t, item_t>)                         \
    child_t & operator()(item_t && value) {                             \
        base_t::operator=(xforward(value));                             \
        return (child_t &)base_t::__the_owner();                        \
    }                                                                   \
                                                                        \
    template<class item_t = __xstruct_rr<typename base_t::__set_t>>     \
    requires(__can_prop_assign<base_t, item_t>)                         \
    child_t & operator()(item_t & value) {                              \
        base_t::operator=(value);                                       \
        return (child_t &)base_t::__the_owner();                        \
    }                                                                   \
}

template<class the_t, class child_t, class base_t>
struct __pubget : base_t{
    struct __prop{ enum{ value = true }; };

    using __get_t = typename base_t::__get_t;
    using base_t::operator __get_t;

    static constexpr bool im_xstruct_prop_get  = true;

    __get_t operator()() const {
        return base_t::operator __get_t();
    }
};

__xprop_meta(__pubget_pubset, public , public);
__xprop_meta(__pubget_proset, public , private, friend child_t;);
__xprop_meta(__pubget_priset, public , private);
__xprop_meta(__proget_pubset, private, public , friend child_t;);
__xprop_meta(__priget_pubset, private, public);
#undef  __xprop_meta
#undef  __xprop_operator


template<class = void>
using __fields          = voidp;
using __child_fields_t  = voidp;

struct __field_base_t{
    static constexpr auto __self_offset(){
        return & __child_t::__dummy;
    }
};

template<class type_t>
union __xstruct_member_offset{
    type_t  member_ptr;
    uxx     offset;
};

#define __xstruct_offset(...)       __xstruct_member_offset<decltype(__VA_ARGS__)/*兼容部分编译器，需要提供此参数*/>{__VA_ARGS__}.offset

#define xthe                                                                                        \
(*(the_t *)(                                                                                        \
    u08p(this) - __xstruct_offset(__field_base_t::__self_offset()) - (                              \
        (uxx)(__fields<__child_t> *)(__child_fields_t *)1024/*nullptr 不起作用，需要有偏移*/ - 1024 \
    )  + (                                                                                          \
        (uxx)(the_t *)(__child_t *)1024 - 1024                                                      \
    )                                                                                               \
))


#define xthex                       ((final_t &)xthe)
#define xprop                       ((__fields<the_t> &)xthe)

#define xprops()                                                                                    \
public:                                                                                             \
    template<class __child_t = the_t>                                                               \
    struct __fields : __fields_hubx<__child_t>{                                                     \
    private:                                                                                        \
        friend the_t;                                                                               \
        using __child_fields_t = typename __child_t::template __fields<__child_t>;

#define xprops_operator()                                                                           \
    __fields<> * operator->() const { return (__fields<> *)this; }

#define __get_set(MOD,MODS,NAME,...)                                                                \
MOD:                                                                                                \
    template<class __field_base_t>                                                                  \
    struct __field_ ## NAME;                                                                        \
                                                                                                    \
    struct __field_base_ ## NAME{                                                                   \
        using __default_type_t = __xstruct_rv<__xstruct_repeat<__VA_ARGS__>>;                       \
        using __field_base_t = __field_base_ ## NAME;                                               \
                                                                                                    \
        __field_base_ ## NAME(__field_base_ ## NAME const &)        = delete;                       \
        void operator=(__field_base_ ## NAME const &)               = delete;                       \
    protected:                                                                                      \
        static constexpr auto __self_offset(){                                                      \
            return & __fields<the_t>::NAME;                                                         \
        }                                                                                           \
                                                                                                    \
        auto & __the_owner() const {                                                                \
            return xthe;                                                                            \
        }                                                                                           \
    };                                                                                              \
                                                                                                    \
    MODS<the_t, __child_t, __field_ ## NAME<__field_base_ ## NAME>> NAME;                           \
                                                                                                    \
    template<class __field_base_t>                                                                  \
    struct __field_ ## NAME : __field_base_ ## NAME

#define xpubget_pubsetx(NAME,...)   __get_set(public,    __pubget_pubset, NAME, __VA_ARGS__)
#define xpubget_prosetx(NAME,...)   __get_set(public,    __pubget_proset, NAME, __VA_ARGS__)
#define xpubget_prisetx(NAME,...)   __get_set(public,    __pubget_priset, NAME, __VA_ARGS__)
#define xproget_pubsetx(NAME,...)   __get_set(public,    __proget_pubset, NAME, __VA_ARGS__)
#define xproget_prosetx(NAME,...)   __get_set(protected, __pubget_pubset, NAME, __VA_ARGS__)
#define xproget_prisetx(NAME,...)   __get_set(protected, __pubget_priset, NAME, __VA_ARGS__)
#define xpriget_pubsetx(NAME,...)   __get_set(public,    __priget_pubset, NAME, __VA_ARGS__)
#define xpriget_prosetx(NAME,...)   __get_set(protected, __priget_pubset, NAME, __VA_ARGS__)
#define xpriget_prisetx(NAME,...)   __get_set(private,   __pubget_pubset, NAME, __VA_ARGS__)

// 避免 NAME 是个宏扩展，所以这里再套一层
#define __xprefix_m(NAME)           m_ ## NAME
#define xpubget_pubset(NAME,...)    __get_set(public,    __pubget_pubset, NAME, __VA_ARGS__) { xr{ return __get_t(xthe.__xprefix_m(NAME)); } xw{xthe.__xprefix_m(NAME) = value; } }
#define xpubget_proset(NAME,...)    __get_set(public,    __pubget_proset, NAME, __VA_ARGS__) { xr{ return __get_t(xthe.__xprefix_m(NAME)); } xw{xthe.__xprefix_m(NAME) = value; } }
#define xpubget_priset(NAME,...)    __get_set(public,    __pubget_priset, NAME, __VA_ARGS__) { xr{ return __get_t(xthe.__xprefix_m(NAME)); } xw{xthe.__xprefix_m(NAME) = value; } }
#define xproget_pubset(NAME,...)    __get_set(public,    __proget_pubset, NAME, __VA_ARGS__) { xr{ return __get_t(xthe.__xprefix_m(NAME)); } xw{xthe.__xprefix_m(NAME) = value; } }
#define xproget_proset(NAME,...)    __get_set(protected, __pubget_pubset, NAME, __VA_ARGS__) { xr{ return __get_t(xthe.__xprefix_m(NAME)); } xw{xthe.__xprefix_m(NAME) = value; } }
#define xproget_priset(NAME,...)    __get_set(protected, __pubget_priset, NAME, __VA_ARGS__) { xr{ return __get_t(xthe.__xprefix_m(NAME)); } xw{xthe.__xprefix_m(NAME) = value; } }
#define xpriget_pubset(NAME,...)    __get_set(public,    __priget_pubset, NAME, __VA_ARGS__) { xr{ return __get_t(xthe.__xprefix_m(NAME)); } xw{xthe.__xprefix_m(NAME) = value; } }
#define xpriget_proset(NAME,...)    __get_set(protected, __priget_pubset, NAME, __VA_ARGS__) { xr{ return __get_t(xthe.__xprefix_m(NAME)); } xw{xthe.__xprefix_m(NAME) = value; } }
#define xpriget_priset(NAME,...)    __get_set(private,   __pubget_pubset, NAME, __VA_ARGS__) { xr{ return __get_t(xthe.__xprefix_m(NAME)); } xw{xthe.__xprefix_m(NAME) = value; } }

#define xpubget(NAME,...)           __get_set(public,    __pubget, NAME, __VA_ARGS__) { xr{ return __get_t(xthe.__xprefix_m(NAME)); } }
#define xproget(NAME,...)           __get_set(protected, __pubget, NAME, __VA_ARGS__) { xr{ return __get_t(xthe.__xprefix_m(NAME)); } }
#define xpriget(NAME,...)           __get_set(private,   __pubget, NAME, __VA_ARGS__) { xr{ return __get_t(xthe.__xprefix_m(NAME)); } }

#define xpubgetx(NAME,...)          __get_set(public,    __pubget, NAME, __VA_ARGS__)
#define xprogetx(NAME,...)          __get_set(protected, __pubget, NAME, __VA_ARGS__)
#define xprigetx(NAME,...)          __get_set(private,   __pubget, NAME, __VA_ARGS__)

#define xpubset(NAME,...)           __get_set(public,    __pubget_pubset, NAME, __VA_ARGS__) { xw{xthe.__xprefix_m(NAME) = value; } }
#define xproset(NAME,...)           __get_set(protected, __pubget_pubset, NAME, __VA_ARGS__) { xw{xthe.__xprefix_m(NAME) = value; } }
#define xpriset(NAME,...)           __get_set(private,   __pubget_pubset, NAME, __VA_ARGS__) { xw{xthe.__xprefix_m(NAME) = value; } }

#define xpubsetx(NAME,...)          __get_set(public,    __pubget_pubset, NAME, __VA_ARGS__)
#define xprosetx(NAME,...)          __get_set(protected, __pubget_pubset, NAME, __VA_ARGS__)
#define xprisetx(NAME,...)          __get_set(private,   __pubget_pubset, NAME, __VA_ARGS__)

#define xusing_protected_field      protected: using __fields_hubx<__child_t>

#define xrx(...)                                                                                    \
    using __get_t = __field_first<                                                                  \
        typename __field_base_t::__default_type_t, __xstruct_repeat<__VA_ARGS__>                    \
    >;                                                                                              \
    operator __get_t() const

#define xwx(...)                                                                                    \
    using __set_t = __field_first<                                                                  \
        __xstruct_rr<typename __field_base_t::__default_type_t>, __xstruct_repeat<__VA_ARGS__>      \
    >;                                                                                              \
    template<class __value_t = __set_t>                                                             \
    requires(__can_prop_assign<__set_t, __value_t>)                                                 \
    void operator=(__value_t && value)

#define xr      xrx()
#define xw      xwx()

#define xprops_operator_plus(FIELDS,...)                                                            \
    typename __xstruct_mix_prop<                                                                    \
        __field_first< /*这么写可以使用 xprops_operator_plus() 宏可以使用 const 修饰*/              \
            typename __field_base_t::__default_type_t, /* 如果用 using 提取出来就不行 */            \
            __xstruct_rr<__xstruct_repeat<__VA_ARGS__>>                                             \
        >                                                                                           \
    >::template __fields<> * operator->() const {                                                   \
        return (typename __xstruct_mix_prop<                                                        \
            __field_first<                                                                          \
                typename __field_base_t::__default_type_t,                                          \
                __xstruct_rr<__xstruct_repeat<__VA_ARGS__>>                                         \
            >                                                                                       \
        >::template __fields<> *)(& FIELDS);                                                        \
    }

#endif
